import logging

from django.shortcuts import render

# Create your views here.
from fdfs_client.client import get_tracker_conf, Fdfs_client
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.status import HTTP_404_NOT_FOUND, HTTP_400_BAD_REQUEST, HTTP_500_INTERNAL_SERVER_ERROR,HTTP_403_FORBIDDEN
from rest_framework.viewsets import ModelViewSet
from rest_framework.mixins import CreateModelMixin
from rest_framework.viewsets import ReadOnlyModelViewSet

from config.fastdfsConfig import FASTDFS_SERVER_DOMAIN
from drfstudy27.settings import alipay
from .serializers import *
from shopping.models import Classification, Commodity, CommodityImg
from rest_framework.permissions import IsAuthenticated
from utils.permission import wrap_permission, TeacherPermission, auto_user, update_auto_user, destroy_auto_user

# 导入日志器
logger = logging.getLogger(__name__)
# tracker server
tracker_path = get_tracker_conf('utils/fastdfs/client.conf')
client = Fdfs_client(tracker_path)


class ClassificationViewSet(ModelViewSet):
    queryset = Classification.objects.filter(is_delete=False, parent=None)
    serializer_class = ParentClassificationSerializer
    permission_classes = [IsAuthenticated]

    @wrap_permission(TeacherPermission)
    def create(self, request, *args, **kwargs):
        return ModelViewSet.create(self, request, *args, **kwargs)

    @wrap_permission(TeacherPermission)
    def update(self, request, *args, **kwargs):
        return ModelViewSet.update(self, request, *args, **kwargs)

    @wrap_permission(TeacherPermission)
    def destroy(self, request, *args, **kwargs):
        return ModelViewSet.destroy(self, request, *args, **kwargs)

    @action(methods=['get'], detail=True)
    def commodity(self, request, pk):
        try:
            classification = Classification.objects.filter(is_delete=False).get(id=pk)
        except Classification.DoesNotExist:
            return Response(status=HTTP_404_NOT_FOUND)
        classification_attr = 'classification1'  # 默认为顶层一级类目
        classification_name = classification.name  # 类目名 展示自身的类目名
        if classification.parent:
            # 纠正修改为子类目
            classification_attr = 'classification2'
            classification_name = f'{classification.parent.name}--{classification.name}'
        data = getattr(classification, classification_attr).filter(is_delete=False, status=1)
        return Response({
            'classification': classification_name,
            'commodity': CommoditySerializer(data, many=True).data
        })


class CommodityViewSet(ModelViewSet):
    queryset = Commodity.objects.filter(is_delete=False)
    serializer_class = CommoditySerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        if self.action in ['list', 'retrieve']:
            return Commodity.objects.filter(is_delete=False, status=1)
        return self.queryset

    @wrap_permission(TeacherPermission)
    def create(self, request, *args, **kwargs):
        return ModelViewSet.create(self, request, *args, **kwargs)

    @wrap_permission(TeacherPermission)
    def update(self, request, *args, **kwargs):
        return ModelViewSet.update(self, request, *args, **kwargs)

    @wrap_permission(TeacherPermission)
    def destroy(self, request, *args, **kwargs):
        return ModelViewSet.destroy(self, request, *args, **kwargs)

    @action(methods=['post'], detail=True)
    def img(self, request, pk):
        # 获取需要操作的商品
        try:
            commodity = self.get_queryset().get(id=pk)
        except Commodity.DoesNotExist:
            return Response(status=HTTP_404_NOT_FOUND)
        # 得到上传的文件数据
        file = request.FILES.get('file')
        # 判断是否是图片数据，文件类型是否是图片
        if not file or file.content_type not in ('image/png', 'image/jpeg', 'image/gif'):
            # 不是图片，返回客户端传入错误数据
            return Response(status=HTTP_400_BAD_REQUEST)
        # 是图片，交给fastdfs，存储到可用的storage服务上
        # 得到文件后缀名，如果没有默认用png
        try:
            images_ext_name = file.name.split('.')[-1]
        except Exception as e:
            logger.info('图片拓展名异常: %s' % e)
            images_ext_name = 'png'
        # 上传图片数据，通过字节流
        try:
            upload_res = client.upload_by_buffer(file.read(), file_ext_name=images_ext_name)
        except Exception as e:
            logger.error('图片上传异常: %s' % e)
            return Response(status=HTTP_500_INTERNAL_SERVER_ERROR)
        else:
            if upload_res.get('Status') != 'Upload successed.':
                logger.warning('图片上传失败')
                return Response(status=HTTP_500_INTERNAL_SERVER_ERROR)
            # 得到返回的file_id
            image_name = upload_res.get('Remote file_id').decode()
            image_url = FASTDFS_SERVER_DOMAIN + image_name

            # 保存图片地址
            CommodityImg.objects.create(src=image_url, commodity=commodity)

            # 返回
            return Response({'data': image_url})

    @action(methods=['get'], detail=False)
    def optimization(self, request):
        queryset = self.get_queryset().order_by('-comments').order_by('-create_time')
        return Response(self.get_serializer(queryset[:5], many=True).data)


class ShoppingCartViewSet(ModelViewSet):
    serializer_class = ShoppingCartSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):  # 通过当前登录用户查看自身的购物车数据
        return self.request.user.shoppingcart_set.all()

    @auto_user
    def create(self, request, *args, **kwargs):
        return ModelViewSet.create(self, request, *args, **kwargs)

    @update_auto_user
    def update(self, request, *args, **kwargs):
        return ModelViewSet.update(self, request, *args, **kwargs)

    @destroy_auto_user
    def destroy(self, request, *args, **kwargs):
        return ModelViewSet.destroy(self, request, *args, **kwargs)


class OrderViewSet(ReadOnlyModelViewSet, CreateModelMixin):
    serializer_class = OrderSerializer

    def get_queryset(self):
        return self.request.user.order_set.all()

    @action(methods=['put'], detail=False)
    def status(self, request):
        # 得到支付宝回调过来的数据，在请求地址里面
        query_dict = request.query_params  # 获得地址栏参数
        data = query_dict.dict()
        # 不要直接修改订单状态，核实身份
        try:
            sign = data.pop('sign')  # 相当于token认证
        except KeyError:
            return Response(status=HTTP_400_BAD_REQUEST)
        # 验证sign
        # res = alipay.verify(data, sign)
        # if not res:
        #     return Response(status=HTTP_403_FORBIDDEN)
        # 得到订单编号、支付宝交易号
        order_id = data.get('out_trade_no')  # 订单编号
        trade_no = data.get('trade_no')  # 支付宝交易号
        # 保存支付信息，修改订单状态
        with transaction.atomic():
            save_point = transaction.savepoint()

            try:
                Payment.objects.create(order_id=order_id, trade_id=trade_no)
                Order.objects.filter(order_id=order_id, status=1).update(status=2)
            except Exception as e:
                transaction.savepoint_rollback(save_point)
                raise serializers.ValidationError(e)
            else:
                transaction.savepoint_commit(save_point)
        return Response({'order_id': order_id, 'trade_id': trade_no})


class PaymentViewSet(ReadOnlyModelViewSet):
    queryset = Payment.objects.all()
    serializer_class = PaymentSerializer

    @action(methods=['get'], detail=True)
    def pay(self, request, pk):
        # 获取订单信息，必须是当前登录用户的订单，并且是没有支付的
        try:
            order = Order.objects.get(order_id=pk, user=request.user, status=1)
        except Order.DoesNotExist:
            return Response(status=HTTP_404_NOT_FOUND)
        # 通过支付宝对象处理订单信息
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order.order_id,  # 订单号
            total_amount=str(order.total_amount),  # 要支付的金额
            subject=f'PROMOTE系统{order.order_id}',  # 订单标题
            return_url='http://127.0.0.1:8080/home/order/success'
        )
        # 将订单信息发送给支付宝
        pay_url = 'https://openapi.alipaydev.com/gateway.do?' + order_string

        # 返回支付页面地址
        return Response({'pay_url': pay_url})
